package iohelper

import "fmt"

type buffWriter struct {
	buff []byte
	pos  int
}

func (w *buffWriter) RemainLen() int {
	return len(w.buff) - w.pos
}

func (w *buffWriter) RemainBytes() []byte {
	return w.buff[w.pos:]
}

func (w *buffWriter) SeekFromCurrent(n int) error {
	l := len(w.buff)
	if w.pos > l {
		return ErrEOF
	}

	w.pos += n
	if w.pos > l || w.pos < 0 {
		w.pos = l
	}
	return nil
}

func (w *buffWriter) ResetPos() {
	w.pos = 0
}

func (w *buffWriter) WriteByte(v byte) (err error) {
	if w.RemainLen() > 0 {
		w.buff[w.pos] = v
		w.pos++
	} else {
		return ErrEOF
	}
	return
}

func (w *buffWriter) WriteUint16(v uint16) (err error) {
	if w.RemainLen() >= 2 {
		byteOrd.PutUint16(w.buff[w.pos:], v)
		w.pos += 2
	} else {
		return ErrEOF
	}
	return
}

func (w *buffWriter) WriteUint32(v uint32) (err error) {
	if w.RemainLen() >= 4 {
		byteOrd.PutUint32(w.buff[w.pos:], v)
		w.pos += 4
	} else {
		return ErrEOF
	}
	return
}

func (w *buffWriter) WriteUint64(v uint64) (err error) {
	if w.RemainLen() >= 8 {
		byteOrd.PutUint64(w.buff[w.pos:], v)
		w.pos += 8
	} else {
		return ErrEOF
	}
	return
}

func (w *buffWriter) Write(buf []byte) (n int, err error) {
	if w.RemainLen() > 0 {
		n = copy(w.buff[w.pos:], buf)
		w.pos += n
	} else {
		err = ErrEOF
	}
	return
}

// 读取整数值
func (w *buffWriter) WriteIntNum(numPtr any) (n int, err error) {
	var num uint64
	switch v := numPtr.(type) {
	case *int8:
		num = uint64(*v)
	case *uint8:
		num = uint64(*v)
	case *int16:
		num = uint64(*v)
	case *uint16:
		num = uint64(*v)
	case *int32:
		num = uint64(*v)
	case *uint32:
		num = uint64(*v)
	case *int64:
		num = uint64(*v)
	case *uint64:
		num = uint64(*v)
	case *int:
		num = uint64(*v)
	default:
		return n, fmt.Errorf("不支持的类型 %v ", v)
	}
	return w.WriteDynInt(num)
}

// 返回:   数值      长度   错误
func (w *buffWriter) WriteDynInt(v uint64) (n int, err error) {
	l := len(w.buff)
	var b byte
	for {
		b = byte(v & cByteDataMask) // 小端在前
		v >>= 7
		if v > 0 {
			b |= cByteHaveDataMask
		}
		w.buff[w.pos] = b
		w.pos++
		n++
		if v == 0 {
			break // 读完了
		} else if w.pos >= l {
			err = fmt.Errorf("ReadDynInt: 数据未读完, 长度不够")
		}
	}
	return
}

func NewBuffWriter(buff []byte) *buffWriter {
	return &buffWriter{buff: buff}
}
